package com.ssy.lingxi.purchase.serviceimpl.purchaseplan;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.purchase.api.dto.request.*;
import com.ssy.lingxi.purchase.api.dto.response.*;
import com.ssy.lingxi.purchase.api.enums.common.CommonBooleanEnum;
import com.ssy.lingxi.purchase.api.enums.needplan.NeedPlanInnerOperationStatusEnum;
import com.ssy.lingxi.purchase.api.enums.needplan.NeedPlanInnerRecordStatusEnum;
import com.ssy.lingxi.purchase.api.enums.purchase.PurchasePlanOperateEnum;
import com.ssy.lingxi.purchase.api.enums.purchase.PurchasePlanStatusEnum;
import com.ssy.lingxi.purchase.api.enums.purchase.StatusEnum;
import com.ssy.lingxi.purchase.api.enums.purchseplan.PurchasePlanInnerStatusEnum;
import com.ssy.lingxi.purchase.entity.needplan.NeedPlan;
import com.ssy.lingxi.purchase.entity.needplan.NeedPlanInnerRecord;
import com.ssy.lingxi.purchase.entity.purchaseplan.PurchasePlan;
import com.ssy.lingxi.purchase.entity.purchaseplan.PurchasePlanDetail;
import com.ssy.lingxi.purchase.entity.purchaseplan.PurchasePlanInnerRecord;
import com.ssy.lingxi.purchase.entity.purchaseplan.QPurchasePlan;
import com.ssy.lingxi.purchase.repository.needplan.NeedPlanRecordRepository;
import com.ssy.lingxi.purchase.repository.needplan.NeedPlanRepository;
import com.ssy.lingxi.purchase.repository.purchaseplan.PurchasePlanDetailRepository;
import com.ssy.lingxi.purchase.repository.purchaseplan.PurchasePlanRecordRepository;
import com.ssy.lingxi.purchase.repository.purchaseplan.PurchasePlanRepository;
import com.ssy.lingxi.purchase.service.purchaseplan.PurchasePlanService;
import com.ssy.lingxi.purchase.utils.DateUtil;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.enums.PurchasePlanOperateTypeEnum;
import com.ssy.lingxi.report.api.feign.ReportControllerFeign;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.workflow.api.feign.ProcessFeign;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import com.ssy.lingxi.workflow.api.model.vo.request.InternalProcessQueryVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskExecuteVO;
import com.ssy.lingxi.workflow.api.model.vo.request.TaskStartVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleProcessDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 采购能力 - 采购计划管理 - 业务实现类
 *
 * @author fhj
 * @version 2.0.0
 * @date 2021/02/26
 */
@Slf4j
@Service
public class PurchasePlanServiceImpl implements PurchasePlanService {

    @Resource
    private ProcessFeign processFeign;
    @Resource
    private NeedPlanRepository needPlanRepository;
    @Resource
    private PurchasePlanRepository purchasePlanRepository;
    @Resource
    private PurchasePlanDetailRepository purchasePlanDetailRepository;
    @Resource
    private PurchasePlanRecordRepository purchasePlanRecordRepository;
    @Resource
    private NeedPlanRecordRepository needPlanRecordRepository;
    @Resource
    private ReportControllerFeign reportControllerFeign;
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    @Override
    @ApiOperation(value = "内部状态")
    public Wrapper<List<Map<String, Object>>> inner() {
        return Wrapper.success(PurchasePlanInnerStatusEnum.getAll());
    }

    @Override
    @ApiOperation(value = "列表（所有）")
    public Wrapper<PageData<PurchasePlanListResponse>> allList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {
        return Wrapper.success(commonList(qo, user));
    }

    @Override
    @ApiOperation(value = "列表（待提交审核）")
    public Wrapper<PageData<PurchasePlanListResponse>> toBeSubmitExamList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {
        qo.setInnerStatusList(Stream.of(
                PurchasePlanInnerStatusEnum.TO_BE_SUBMIT_EXAM.getCode(),
                PurchasePlanInnerStatusEnum.NOT_PASSED1.getCode(),
                PurchasePlanInnerStatusEnum.NOT_PASSED2.getCode()
        ).collect(Collectors.toList()));
        return Wrapper.success(commonList(qo, user));
    }

    @Override
    @ApiOperation(value = "列表（待一级审核）")
    public Wrapper<PageData<PurchasePlanListResponse>> toBeFirstExamList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {
        qo.setInnerStatusList(Stream.of(
                PurchasePlanInnerStatusEnum.TO_BE_EXAM1.getCode()
        ).collect(Collectors.toList()));
        return Wrapper.success(commonList(qo, user));
    }

    @Override
    @ApiOperation(value = "列表（待二级审核）")
    public Wrapper<PageData<PurchasePlanListResponse>> toBeSecondExamList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {
        qo.setInnerStatusList(Stream.of(
                PurchasePlanInnerStatusEnum.TO_BE_EXAM2.getCode()
        ).collect(Collectors.toList()));
        return Wrapper.success(commonList(qo, user));
    }

    @Override
    @ApiOperation(value = "列表（待执行）")
    public Wrapper<PageData<PurchasePlanListResponse>> toBeExecuteList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {
        qo.setInnerStatusList(Stream.of(
                PurchasePlanInnerStatusEnum.TO_BE_EXECUTE.getCode()
        ).collect(Collectors.toList()));
        return Wrapper.success(commonList(qo, user));
    }

    @Override
    @ApiOperation(value = "详情")
    public Wrapper<PurchasePlanResponse> details(CommonIdRequest dto, UserLoginCacheDTO user) {
        //根据ID获取采购计划详情
        PurchasePlan purchasePlan = purchasePlanRepository.findById(dto.getId()).orElse(null);
        if (purchasePlan == null) {
            return Wrapper.fail(ResponseCode.PURCHASE_PURCHASE_PLAN_INFORMATION_NOT_FOUND_BY_ID);
        }

        //拷贝
        PurchasePlanResponse response = new PurchasePlanResponse();
        BeanUtils.copyProperties(purchasePlan, response);

        //封装内部状态名称
        response.setInnerStatusName(PurchasePlanInnerStatusEnum.getMessage(response.getInnerStatus()));

        //根据采购计划ID获取采购计划内部工作流记录集合
        List<PurchasePlanInnerRecord> innerRecords = purchasePlanRecordRepository.findByPurchasePlanId(dto.getId());
        response.setInnerRecords(innerRecords.stream().map(a -> {
            PurchasePlanInnerRecordResponse recordResponse = new PurchasePlanInnerRecordResponse();
            BeanUtils.copyProperties(a, recordResponse);
            //国际化翻译操作
            recordResponse.setOperate(PurchasePlanOperateEnum.getName(a.getOperate()));
            recordResponse.setStatus(PurchasePlanStatusEnum.getName(a.getStatus()));
            recordResponse.setOpinion(StatusEnum.AGREE.getCHName().equals(a.getOpinion())? StatusEnum.getName(a.getOpinion()) : a.getOpinion());
            return recordResponse;
        }).collect(Collectors.toList()));

        //根据采购计划ID获取采购计划明细
        List<PurchasePlanDetail> details = purchasePlanDetailRepository.findByPurchasePlanId(dto.getId());
        response.setDetails(details.stream().map(a -> {
            PurchasePlanDetailsResponse purchasePlanDetailsResponse = new PurchasePlanDetailsResponse();
            BeanUtils.copyProperties(a, purchasePlanDetailsResponse);
            purchasePlanDetailsResponse.setPurchaseNeedPlanDetailList(
                    a.getPurchaseNeedPlanDetailList().stream().map(b -> {
                        PurchaseNeedPlanDetailResponse PNPDResponse = new PurchaseNeedPlanDetailResponse();
                        BeanUtils.copyProperties(b, PNPDResponse);
                        return PNPDResponse;
                    }).collect(Collectors.toList())
            );
            return purchasePlanDetailsResponse;
        }).collect(Collectors.toList()));

        //获取采购计划内部工作流程, 调用工作流服务 -> 查询单一的内部流程的定义
        InternalProcessQueryVO internalProcessQueryVO = new InternalProcessQueryVO();
        internalProcessQueryVO.setProcessKey(response.getInnerProcessKey());
        internalProcessQueryVO.setTaskId(response.getInnerTaskId());
        internalProcessQueryVO.setMemberId(response.getMemberId());
        Wrapper<SimpleProcessDefVO> wrapper = processFeign.findSimpleInternalTaskDefinitions(internalProcessQueryVO);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("工作流服务异常:" + wrapper.getMessage());
            throw new BusinessException(ResponseCode.ENHANCE_WORKFLOW_ERROR);
        }
        //封装采购计划内部工作流程
        List<TaskStepResponse> innerTaskList = wrapper.getData().getTasks().stream().map(a -> {
            TaskStepResponse taskStepVO = new TaskStepResponse();
            taskStepVO.setStep(a.getTaskStep());
            taskStepVO.setRoleName(a.getRoleName());
            taskStepVO.setTaskName(a.getTaskName());
            if (wrapper.getData().getCurrentStep() == 0 || wrapper.getData().getCurrentStep() >= a.getTaskStep()) {
                taskStepVO.setIsExecute(CommonBooleanEnum.YES.getCode());
            } else {
                taskStepVO.setIsExecute(CommonBooleanEnum.NO.getCode());
            }
            return taskStepVO;
        }).collect(Collectors.toList());
        response.setInnerTaskList(innerTaskList);

        return Wrapper.success(response);
    }

    @Override
    @ApiOperation(value = "采购计划明细")
    public Wrapper<PageData<PurchasePlanDetail>> purchasePlanDetail(CommonIdPageRequest dto, UserLoginCacheDTO user) {
        Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").ascending());
        Page<PurchasePlanDetail> page = purchasePlanDetailRepository.findByPurchasePlanId(dto.getId(), pageable);
        return Wrapper.success(new PageData<>(page.getTotalElements(), page.getContent()));
    }

    @Override
    @Transactional
    @ApiOperation(value = "修改")
    public Wrapper<Void> update(UpdatePurchasePlanRequest dto, UserLoginCacheDTO user) {
        //根据ID获取采购计划详情
        PurchasePlan purchasePlan = purchasePlanRepository.findById(dto.getId()).orElse(null);
        if (purchasePlan == null) {
            return Wrapper.fail(ResponseCode.PURCHASE_PURCHASE_PLAN_INFORMATION_NOT_FOUND_BY_ID);
        }

        //修改
        purchasePlan.setStartTime(dto.getStartTime() == null ? purchasePlan.getStartTime() : DateUtil.getStartDate(new Date(dto.getStartTime())));
        purchasePlan.setEndTime(dto.getEndTime() == null ? purchasePlan.getEndTime() : DateUtil.getStartDate(new Date(dto.getEndTime())));
        purchasePlan.setSummary(StringUtils.isBlank(dto.getSummary()) ? purchasePlan.getSummary() : dto.getSummary());
        purchasePlanRepository.saveAndFlush(purchasePlan);

        //调用工作流服务 -> 开启内部工作流
        TaskStartVO taskStartVO = new TaskStartVO();
        taskStartVO.setProcessKey(purchasePlan.getInnerProcessKey());
        taskStartVO.setMemberId(purchasePlan.getMemberId());
        taskStartVO.setRoleId(purchasePlan.getRoleId());
        taskStartVO.setDataId(purchasePlan.getId());
        Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.startSimpleProcess(taskStartVO);
        if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
            //更新内部状态、内部任务ID
            purchasePlan.setInnerStatus(wrapper.getData().getStatus());
            purchasePlan.setInnerTaskId(wrapper.getData().getTaskId());
            purchasePlanRepository.saveAndFlush(purchasePlan);
        } else {
            log.error("工作流服务异常:" + wrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "删除")
    public Wrapper<Void> delete(CommonIdRequest dto, UserLoginCacheDTO user) {
        //删除采购计划、采购计划明细、内部工作流记录
        purchasePlanRepository.deleteById(dto.getId());
        purchasePlanDetailRepository.deleteByPurchasePlanId(dto.getId());
        purchasePlanRecordRepository.deleteByPurchasePlanId(dto.getId());

        //根据采购计划ID获取被汇总的需求计划
        List<NeedPlan> needPlanList = needPlanRepository.findAllByPurchasePlanId(dto.getId());
        for (NeedPlan needPlan : needPlanList) {
            //调用工作流服务 -> 开启内部工作流
            TaskStartVO taskStartVO = new TaskStartVO();
            taskStartVO.setProcessKey(needPlan.getInnerProcessKey());
            taskStartVO.setMemberId(needPlan.getMemberId());
            taskStartVO.setRoleId(needPlan.getRoleId());
            taskStartVO.setDataId(needPlan.getId());
            Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.startSimpleProcess(taskStartVO);
            if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
                //调用工作流服务 -> 执行流程任务
                TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
                taskExecuteVO.setMemberId(needPlan.getMemberId());
                taskExecuteVO.setRoleId(needPlan.getRoleId());
                taskExecuteVO.setDataId(needPlan.getId());
                taskExecuteVO.setTaskId(wrapper.getData().getTaskId());
                taskExecuteVO.setAgree(ProcessTaskStatusEnum.DISAGREE.getCode());
                taskExecuteVO.setProcessKey(needPlan.getInnerProcessKey());
                wrapper = processFeign.completeSimpleTask(taskExecuteVO);
                if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
                    //记录需求计划内部工作流记录
                    NeedPlanInnerRecord needPlanInnerRecord = new NeedPlanInnerRecord();
                    needPlanInnerRecord.setNeedPlanId(needPlan.getId());
                    needPlanInnerRecord.setUserId(user.getUserId());
                    needPlanInnerRecord.setMemberId(user.getMemberId());
                    needPlanInnerRecord.setRoleId(user.getMemberRoleId());
                    needPlanInnerRecord.setStep(needPlan.getInnerStatus());
                    needPlanInnerRecord.setOperator(user.getUserName());
                    needPlanInnerRecord.setDepartment(user.getUserOrgName());
                    needPlanInnerRecord.setJobTitle(user.getUserJobTitle());
                    needPlanInnerRecord.setStatus(NeedPlanInnerRecordStatusEnum.TO_BE_COLLECT.getCHMessage());
                    needPlanInnerRecord.setOperate(NeedPlanInnerOperationStatusEnum.UNLOCK.getCHMessage());
                    needPlanInnerRecord.setOperateTime(System.currentTimeMillis());
                    needPlanRecordRepository.saveAndFlush(needPlanInnerRecord);

                    //更新内部状态、内部任务ID、采购计划ID
                    needPlan.setInnerStatus(wrapper.getData().getStatus());
                    needPlan.setInnerTaskId(wrapper.getData().getTaskId());
                    needPlan.setPurchasePlanId(null);
                    needPlanRepository.saveAndFlush(needPlan);

                    //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
                    addOperateNotice(
                            user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                            PurchasePlanOperateTypeEnum.TO_BE_SUMMARY_COUNT.getCode(), null,
                            null, null
                    );
                } else {
                    log.error("工作流服务异常:" + wrapper.getMessage());
                    return Wrapper.fail(ResponseCode.ENHANCE_WORKFLOW_ERROR);
                }
            } else {
                log.error("工作流服务异常:" + wrapper.getMessage());
                return Wrapper.fail(ResponseCode.ENHANCE_WORKFLOW_ERROR);
            }
        }

        //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        addOperateNotice(
                user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                null, null,
                PurchasePlanOperateTypeEnum.TO_BE_COMMIT_VALIFY_COUNT.getCode(), 1L
        );

        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "提交审核")
    public Wrapper<Void> submitExam(CommonIdRequest dto, UserLoginCacheDTO user) {
        //根据ID获取采购计划详情
        PurchasePlan purchasePlan = purchasePlanRepository.findById(dto.getId()).orElse(null);
        if (purchasePlan == null) {
            return Wrapper.fail(ResponseCode.PURCHASE_PURCHASE_PLAN_INFORMATION_NOT_FOUND_BY_ID);
        }

        //调用工作流服务 -> 执行流程任务
        TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
        taskExecuteVO.setMemberId(purchasePlan.getMemberId());
        taskExecuteVO.setRoleId(purchasePlan.getRoleId());
        taskExecuteVO.setDataId(purchasePlan.getId());
        taskExecuteVO.setTaskId(purchasePlan.getInnerTaskId());
        taskExecuteVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
        taskExecuteVO.setProcessKey(purchasePlan.getInnerProcessKey());
        Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
            //记录采购计划内部工作流记录
            PurchasePlanInnerRecord purchasePlanInnerRecord = new PurchasePlanInnerRecord();
            purchasePlanInnerRecord.setPurchasePlanId(purchasePlan.getId());
            purchasePlanInnerRecord.setUserId(user.getUserId());
            purchasePlanInnerRecord.setMemberId(user.getMemberId());
            purchasePlanInnerRecord.setRoleId(user.getMemberRoleId());
            purchasePlanInnerRecord.setStep(purchasePlan.getInnerStatus());
            purchasePlanInnerRecord.setOperator(user.getUserName());
            purchasePlanInnerRecord.setDepartment(user.getUserOrgName());
            purchasePlanInnerRecord.setJobTitle(user.getUserJobTitle());
            purchasePlanInnerRecord.setStatus(PurchasePlanStatusEnum.EXAMINE1.getCHName());
            purchasePlanInnerRecord.setOperate(PurchasePlanOperateEnum.TO_BE_SUBMIT.getCHName());
            purchasePlanInnerRecord.setOperateTime(System.currentTimeMillis());
            purchasePlanRecordRepository.saveAndFlush(purchasePlanInnerRecord);

            //更新内部状态、内部任务ID、操作人（冗余）、部门（冗余）、职位（冗余）
            purchasePlan.setInnerStatus(wrapper.getData().getStatus());
            purchasePlan.setInnerTaskId(wrapper.getData().getTaskId());
            purchasePlan.setOperator(user.getUserName());
            purchasePlan.setSection(user.getUserOrgName());
            purchasePlan.setJobTitle(user.getUserJobTitle());
            purchasePlanRepository.saveAndFlush(purchasePlan);
        } else {
            log.error("工作流服务异常:" + wrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        addOperateNotice(
                user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), 1L,
                PurchasePlanOperateTypeEnum.TO_BE_COMMIT_VALIFY_COUNT.getCode(), 1L
        );

        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "审核（一级）")
    public Wrapper<Void> firstExam(CommonExamRequest dto, UserLoginCacheDTO user) {
        //如果审核不通过时, 校验审核不通过原因是否为空
        if (dto.getStatus().equals(CommonBooleanEnum.NO.getCode()) && StringUtils.isBlank(dto.getCause())) {
            return Wrapper.fail(ResponseCode.ENHANCE_VALIDATE_DISAGREE_REASON_CAN_NOT_BE_EMPTY);
        }

        //根据ID获取采购计划详情
        PurchasePlan purchasePlan = purchasePlanRepository.findById(dto.getId()).orElse(null);
        if (purchasePlan == null) {
            return Wrapper.fail(ResponseCode.PURCHASE_PURCHASE_PLAN_INFORMATION_NOT_FOUND_BY_ID);
        }

        //调用工作流服务 -> 执行流程任务
        TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
        taskExecuteVO.setMemberId(purchasePlan.getMemberId());
        taskExecuteVO.setRoleId(purchasePlan.getRoleId());
        taskExecuteVO.setDataId(purchasePlan.getId());
        taskExecuteVO.setTaskId(purchasePlan.getInnerTaskId());
        taskExecuteVO.setAgree(dto.getStatus());
        taskExecuteVO.setProcessKey(purchasePlan.getInnerProcessKey());
        Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
            //记录采购计划内部工作流记录
            PurchasePlanInnerRecord purchasePlanInnerRecord = new PurchasePlanInnerRecord();
            purchasePlanInnerRecord.setPurchasePlanId(purchasePlan.getId());
            purchasePlanInnerRecord.setUserId(user.getUserId());
            purchasePlanInnerRecord.setMemberId(user.getMemberId());
            purchasePlanInnerRecord.setRoleId(user.getMemberRoleId());
            purchasePlanInnerRecord.setStep(purchasePlan.getInnerStatus());
            purchasePlanInnerRecord.setOperator(user.getUserName());
            purchasePlanInnerRecord.setDepartment(user.getUserOrgName());
            purchasePlanInnerRecord.setJobTitle(user.getUserJobTitle());
            purchasePlanInnerRecord.setStatus(dto.getStatus().equals(CommonBooleanEnum.YES.getCode()) ? PurchasePlanStatusEnum.EXAMINE2.getCHName() : PurchasePlanStatusEnum.NOT_PASSED1.getCHName());
            purchasePlanInnerRecord.setOperate(PurchasePlanOperateEnum.EXAMINE1.getCHName());
            purchasePlanInnerRecord.setOperateTime(System.currentTimeMillis());
            purchasePlanInnerRecord.setOpinion(dto.getStatus().equals(CommonBooleanEnum.YES.getCode()) ? StatusEnum.AGREE.getCHName() : dto.getCause());
            purchasePlanRecordRepository.saveAndFlush(purchasePlanInnerRecord);

            //更新内部状态、内部任务ID、原因
            purchasePlan.setInnerStatus(wrapper.getData().getStatus());
            purchasePlan.setInnerTaskId(wrapper.getData().getTaskId());
            purchasePlan.setCause(dto.getCause());
            purchasePlanRepository.saveAndFlush(purchasePlan);
        } else {
            log.error("工作流服务异常:" + wrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        if (dto.getStatus().equals(CommonBooleanEnum.YES.getCode())) {
            addOperateNotice(
                    user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                    PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), 1L,
                    PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), 1L
            );
        } else {
            addOperateNotice(
                    user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                    null, null,
                    PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), 1L
            );
        }

        return Wrapper.success();
    }

    @Override
    @Transactional
    @ApiOperation(value = "审核（二级）")
    public Wrapper<Void> secondExam(CommonExamRequest dto, UserLoginCacheDTO user) {
        //如果审核不通过时, 校验审核不通过原因是否为空
        if (dto.getStatus().equals(CommonBooleanEnum.NO.getCode()) && StringUtils.isBlank(dto.getCause())) {
            return Wrapper.fail(ResponseCode.ENHANCE_VALIDATE_DISAGREE_REASON_CAN_NOT_BE_EMPTY);
        }

        //根据ID获取采购计划详情
        PurchasePlan purchasePlan = purchasePlanRepository.findById(dto.getId()).orElse(null);
        if (purchasePlan == null) {
            return Wrapper.fail("根据ID未找到采购计划信息");
        }

        //调用工作流服务 -> 执行流程任务
        TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
        taskExecuteVO.setMemberId(purchasePlan.getMemberId());
        taskExecuteVO.setRoleId(purchasePlan.getRoleId());
        taskExecuteVO.setDataId(purchasePlan.getId());
        taskExecuteVO.setTaskId(purchasePlan.getInnerTaskId());
        taskExecuteVO.setAgree(dto.getStatus());
        taskExecuteVO.setProcessKey(purchasePlan.getInnerProcessKey());
        Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.completeSimpleTask(taskExecuteVO);
        if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
            //记录采购计划内部工作流记录
            PurchasePlanInnerRecord purchasePlanInnerRecord = new PurchasePlanInnerRecord();
            purchasePlanInnerRecord.setPurchasePlanId(purchasePlan.getId());
            purchasePlanInnerRecord.setUserId(user.getUserId());
            purchasePlanInnerRecord.setMemberId(user.getMemberId());
            purchasePlanInnerRecord.setRoleId(user.getMemberRoleId());
            purchasePlanInnerRecord.setStep(purchasePlan.getInnerStatus());
            purchasePlanInnerRecord.setOperator(user.getUserName());
            purchasePlanInnerRecord.setDepartment(user.getUserOrgName());
            purchasePlanInnerRecord.setJobTitle(user.getUserJobTitle());
            purchasePlanInnerRecord.setStatus(dto.getStatus().equals(CommonBooleanEnum.YES.getCode()) ? PurchasePlanStatusEnum.TO_BE_IMPLEMENTED.getCHName() : PurchasePlanStatusEnum.NOT_PASSED2.getCHName());
            purchasePlanInnerRecord.setOperate(PurchasePlanOperateEnum.EXAMINE2.getCHName());
            purchasePlanInnerRecord.setOperateTime(System.currentTimeMillis());
            purchasePlanInnerRecord.setOpinion(dto.getStatus().equals(CommonBooleanEnum.YES.getCode()) ? StatusEnum.AGREE.getCHName() : dto.getCause());
            purchasePlanRecordRepository.saveAndFlush(purchasePlanInnerRecord);

            //更新内部状态、内部任务ID、原因
            purchasePlan.setInnerStatus(wrapper.getData().getStatus());
            purchasePlan.setInnerTaskId(wrapper.getData().getTaskId());
            purchasePlan.setCause(dto.getCause());
            purchasePlanRepository.saveAndFlush(purchasePlan);
        } else {
            log.error("工作流服务异常:" + wrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        if (dto.getStatus().equals(CommonBooleanEnum.YES.getCode())) {
            addOperateNotice(
                    user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                    PurchasePlanOperateTypeEnum.TO_BE_EXECUTE_COUNT.getCode(), 1L,
                    PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), 1L
            );
        } else {
            addOperateNotice(
                    user.getMemberId(), user.getMemberRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                    null, null,
                    PurchasePlanOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), 1L
            );
        }

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "执行")
    public void execute() {
        //获取结束周期小于等于当天时间的采购计划，批量更新采购计划
        List<PurchasePlan> list = purchasePlanRepository.findAllByEndTimeLessThanEqualAndInnerStatus(System.currentTimeMillis(), PurchasePlanInnerStatusEnum.TO_BE_EXECUTE.getCode());
        if (CollectionUtil.isNotEmpty(list)) {
            for (PurchasePlan purchasePlan : list) {
                //调用工作流服务 -> 执行流程任务
                TaskExecuteVO taskExecuteVO = new TaskExecuteVO();
                taskExecuteVO.setMemberId(purchasePlan.getMemberId());
                taskExecuteVO.setRoleId(purchasePlan.getRoleId());
                taskExecuteVO.setDataId(purchasePlan.getId());
                taskExecuteVO.setTaskId(purchasePlan.getInnerTaskId());
                taskExecuteVO.setAgree(ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
                taskExecuteVO.setProcessKey(purchasePlan.getInnerProcessKey());
                Wrapper<SimpleTaskCompleteVO> wrapper = processFeign.completeSimpleTask(taskExecuteVO);
                if (ResponseCode.SUCCESS.getCode() == wrapper.getCode()) {
                    //记录采购计划内部工作流记录
                    PurchasePlanInnerRecord purchasePlanInnerRecord = new PurchasePlanInnerRecord();
                    purchasePlanInnerRecord.setPurchasePlanId(purchasePlan.getId());
                    purchasePlanInnerRecord.setUserId(purchasePlan.getUserId());
                    purchasePlanInnerRecord.setMemberId(purchasePlan.getMemberId());
                    purchasePlanInnerRecord.setRoleId(purchasePlan.getRoleId());
                    purchasePlanInnerRecord.setStep(purchasePlan.getInnerStatus());
                    purchasePlanInnerRecord.setOperator(purchasePlan.getOperator());
                    purchasePlanInnerRecord.setDepartment(purchasePlan.getSection());
                    purchasePlanInnerRecord.setJobTitle(purchasePlan.getJobTitle());
                    purchasePlanInnerRecord.setStatus(PurchasePlanStatusEnum.COMPLETE.getCHName());
                    purchasePlanInnerRecord.setOperate(PurchasePlanOperateEnum.IMPLEMENT_PURCHASE.getCHName());
                    purchasePlanInnerRecord.setOperateTime(System.currentTimeMillis());
                    purchasePlanRecordRepository.saveAndFlush(purchasePlanInnerRecord);

                    //更新内部状态、内部任务ID
                    purchasePlan.setInnerStatus(wrapper.getData().getStatus());
                    purchasePlan.setInnerTaskId(wrapper.getData().getTaskId());
                    purchasePlanRepository.saveAndFlush(purchasePlan);

                    //调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
                    addOperateNotice(
                            purchasePlan.getMemberId(), purchasePlan.getRoleId(), OperateDataSourceEnum.PURCHASE_PLAN.getCode(),
                            null, null,
                            PurchasePlanOperateTypeEnum.TO_BE_EXECUTE_COUNT.getCode(), 1L
                    );
                } else {
                    log.error("采购计划ID为:{}，工作流服务异常:{}", purchasePlan.getId(), wrapper.getMessage());
                }
            }
        }
    }

    /**
     * 公共集合方法
     */
    private PageData<PurchasePlanListResponse> commonList(PurchasePlanListRequest qo, UserLoginCacheDTO user) {

        QPurchasePlan qPurchasePlan = QPurchasePlan.purchasePlan;
        JPAQuery<PurchasePlanListResponse> jpaQuery = jpaQueryFactory
                .select(Projections.constructor(PurchasePlanListResponse.class,
                        qPurchasePlan.id,
                        qPurchasePlan.memberId,
                        qPurchasePlan.roleId,
                        qPurchasePlan.userId,
                        qPurchasePlan.purchasePlanNo,
                        qPurchasePlan.startTime,
                        qPurchasePlan.endTime,
                        qPurchasePlan.summary,
                        qPurchasePlan.department,
                        qPurchasePlan.userName,
                        qPurchasePlan.createTime,
                        qPurchasePlan.innerStatus))
                .from(qPurchasePlan).where(qPurchasePlan.memberId.eq(user.getMemberId()), qPurchasePlan.roleId.eq(user.getMemberRoleId()));

        if (CollectionUtil.isNotEmpty(qo.getInnerStatusList())) {
            jpaQuery.where(qPurchasePlan.innerStatus.in(qo.getInnerStatusList()));
        }
        if (StringUtils.isNotBlank(qo.getPurchasePlanNo())) {
            jpaQuery.where(qPurchasePlan.purchasePlanNo.contains(qo.getPurchasePlanNo()));
        }
        if (StringUtils.isNotBlank(qo.getSummary())) {
            jpaQuery.where(qPurchasePlan.summary.contains(qo.getSummary()));
        }
        if (qo.getStartTime() != null) {
            jpaQuery.where(qPurchasePlan.createTime.goe(qo.getStartTime()));
        }
        if (qo.getEndTime() != null) {
            jpaQuery.where(qPurchasePlan.endTime.loe(qo.getEndTime()));
        }
        //获取列表数据和总记录数
        long totalCount = jpaQuery.fetchCount();
        List<PurchasePlanListResponse> list = jpaQuery.orderBy(qPurchasePlan.createTime.desc()).limit(qo.getPageSize()).offset((long) (qo.getCurrent() - 1) * qo.getPageSize()).fetch();
        //封装内部状态名称
        list.forEach(a -> a.setInnerStatusName(PurchasePlanInnerStatusEnum.getMessage(a.getInnerStatus())));

        return new PageData<>(totalCount, list);
    }

    /**
     * 新增操作通知
     *
     * @param memberId       会员ID
     * @param roleId         角色ID
     * @param dataSource     数据源
     * @param increaseStatus 增加的待办
     * @param increaseNum    增加的数量
     * @param reduceStatus   减少的待办
     * @param reduceNum      减少的数量
     */
    @Async
    public void addOperateNotice(Long memberId, Long roleId, Integer dataSource, Integer increaseStatus, Long increaseNum, Integer reduceStatus, Long reduceNum) {
        try {
            OperateNoticeVO noticeVO = new OperateNoticeVO();
            noticeVO.setMemberId(memberId);
            noticeVO.setRoleId(roleId);
            noticeVO.setDataSource(dataSource);

            //增加的待办与数量
            if (increaseStatus != null) {
                noticeVO.setIncreaseOperateType(increaseStatus);
                noticeVO.setIncreaseCount(increaseNum);
            }

            //减少的待办与数量
            if (reduceStatus != null) {
                noticeVO.setReduceOperateType(reduceStatus);
                noticeVO.setReduceCount(reduceNum);
            }

            reportControllerFeign.addOperateNotice(noticeVO);
        } catch (Exception e) {
            log.info("调用报表服务新增操作通知接口失败：{}", e.getMessage());
        }
    }
}
